#include <iostream>
#include <memory>
#include "Epoller.hpp"
#include "TcpServer.hpp" //处理IO的
#include "Calculator.hpp" //处理业务的（目前用的就是我们之前写的自定义协议）

//安装json：sudo apt install -y libjsoncpp-dev

Calculator calculator;

void DefaultNoMessage(std::weak_ptr<Connection> conn)
{
    if(conn.expired()) return;
    auto connection_ptr = conn.lock();
    std::cout << "上层得到了数据" << connection_ptr->InBuffer() <<std::endl;

    // 拿到数据后就是开始处理数据了，我们现在的业务逻辑比较简单，没有特别耗时的操作
    //Handler方法要输入一个package字符串，字符串从InBuffer里面来
    //处理完后就得到了处理结果：去报头，反序列化，计算，序列化，添加报头
    std::string response_str = calculator.Handler(connection_ptr->InBuffer()); //就这一行就完成了对报文的处理 
    if(response_str.empty()) return; //如果处理结果是空的，说明上层检查就是不完整报文，然后底层循环继续读，底层再从文件描述符里面读，直到读到完整报文
    lg(Debug, "response_str: %s", response_str.c_str());

    //再发送回去，先把数据添加到发送缓冲区里去
    connection_ptr->AppendOutBuffer(response_str);
    //关于发送
    //1，epoll/select/poll，因为写事件是检测发送缓冲区是否有空间的，也就是说写事件经常就是OK的，是就绪的
    //2，如果我们设置对EPOLLOUT写事件关心，而几乎每次都就绪，就会导致epollserver经常返回，会浪费CPU的资源
    //结论：对于读取，我们要设置常关心；而对于写事件，我们要 "按需设置"
    //问题：什么是按需设置？代码
    //问题：怎么处理写？直接写入，如果写入完成就结束；但是写入完成，但是数据没有写完，outbuffer里面还有内容，我们就需要 设置对写事件进行关心了，写完了就去掉对写事件的关心
    //connection_ptr->_send_cb(connection_ptr); //调用这个方法，太简单粗暴了，直接就发送了，但是发送应该是tcpserver来做的，所以我们让tcpserver来发
    auto tcpserver = connection_ptr->_tcp_server_ptr.lock();
    tcpserver->Sender(connection_ptr);
}

int main(int argc, char* argv[])
{
    if(argc != 2)
    {
        std::cout << "please enter with port" << std::endl;
        return 1;
    }
    auto port = std::stoi(argv[1]);

    std::shared_ptr<TcpServer> svr(new TcpServer(port, DefaultNoMessage));
    svr->Init();
    svr->Loop(); 
    return 0;
}